package com.david.mydemo.util;


import com.david.mydemo.ctl_ftp.eunm.AaaaEnum;
import com.david.mydemo.ctl_ftp.model.AaaaLog;
import com.david.mydemo.ctl_ftp.model.AaaaLogRspInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.UUID;


@Slf4j
public class FtpClientUtil {

    //ftp服务器地址
    private String hostname;
    //ftp服务器端口
    private int port;
    //ftp登录账号
    private String username;
    //ftp登录密码
    private String password;

    private static FtpClientUtil ftpClient;


    public static FtpClientUtil getInstance(String host, int port, String username, String password) {
        if (ftpClient == null) {
            ftpClient = new FtpClientUtil(host, port, username, password);
        }
        return ftpClient;
    }

    public FtpClientUtil() {
    }

    /**
     * 初始化FTP服务器
     *
     * @return
     */
    public FtpClientUtil(String hostname, int port, String username, String password) {
        this.hostname = hostname;
        this.port = port;
        this.username = username;
        this.password = password;
    }

    /**
     * 初始化FTP服务器
     *
     * @return
     */
    public FTPClient getFtpClient() {
        FTPClient ftpClient = new FTPClient();
        ftpClient.setControlEncoding("UTF-8");
        try {
            //设置连接超时时间
            ftpClient.setDataTimeout(1000 * 120);
            log.info("连接FTP服务器中:" + hostname + ":" + port);
            //连接ftp服务器
            ftpClient.connect(hostname, port);
            //登录ftp服务器
            ftpClient.login(username, password);
            // 是否成功登录服务器
            int replyCode = ftpClient.getReplyCode();
            if (FTPReply.isPositiveCompletion(replyCode)) {
                log.info("连接FTP服务器成功:" + hostname + ":" + port);
            } else {
                log.error("连接FTP服务器失败:" + hostname + ":" + port);
                closeFtpClient(ftpClient);
            }
        } catch (IOException e) {
            log.error("连接ftp服务器异常", e);
        }
        return ftpClient;
    }


    /**
     * 上传文件
     *
     * @param pathName    路径
     * @param fileName    文件名
     * @param inputStream 输入文件流
     * @return
     */
    public boolean uploadFileToFtp(String pathName, String fileName, InputStream inputStream) {
        boolean isSuccess = false;
        FTPClient ftpClient = getFtpClient();
        try {
            if (ftpClient.isConnected()) {
                log.info("开始上传文件到FTP,文件名称：{},上传路径：{}", fileName, pathName);
                //设置上传文件类型为二进制，否则将无法打开文件
                ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
                //路径切换，如果目录不存在创建目录
                if (!ftpClient.changeWorkingDirectory(pathName)) {
                    log.error("切换到目录失败：{}", pathName);
                    boolean flag = this.changeAndMakeWorkingDir(ftpClient, pathName);
                    if (!flag) {
                        log.error("路径切换(创建目录)失败");
                        return false;
                    }
                }
                //设置被动模式，文件传输端口设置(如上传文件夹成功，不能上传文件，注释这行，否则报错refused:connect)
//                ftpClient.enterLocalPassiveMode();
                ftpClient.storeFile(fileName, inputStream);
                inputStream.close();
                ftpClient.logout();
                isSuccess = true;
                log.info(fileName + "文件上传到FTP成功");
            } else {
                log.error("FTP连接建立失败");
            }
        } catch (Exception e) {
            log.error(fileName + "文件上传异常", e);

        } finally {
            closeFtpClient(ftpClient);
            closeStream(inputStream);
        }
        return isSuccess;
    }

    /**
     * 删除文件
     *
     * @param pathName 路径
     * @param fileName 文件名
     * @return
     */
    public boolean deleteFile(String pathName, String fileName) {
        boolean flag = false;
        FTPClient ftpClient = getFtpClient();
        try {
            log.info("开始删除文件");
            if (ftpClient.isConnected()) {
                //路径切换
                ftpClient.changeWorkingDirectory(pathName);
                ftpClient.enterLocalPassiveMode();
                ftpClient.dele(fileName);
                ftpClient.logout();
                flag = true;
                log.info("删除文件成功");
            } else {
                log.info("删除文件失败");
            }
        } catch (Exception e) {
            log.error(fileName + "文件删除异常", e);
        } finally {
            closeFtpClient(ftpClient);
        }
        return flag;
    }

    /**
     * 关闭FTP连接
     *
     * @param ftpClient
     */
    public void closeFtpClient(FTPClient ftpClient) {
        if (ftpClient.isConnected()) {
            try {
                ftpClient.disconnect();
            } catch (IOException e) {
                log.error("关闭FTP连接异常", e);
            }
        }
    }

    /**
     * 关闭文件流
     *
     * @param closeable
     */
    public void closeStream(Closeable closeable) {
        if (null != closeable) {
            try {
                closeable.close();
            } catch (IOException e) {
                log.error("关闭文件流异常", e);
            }
        }
    }

    /**
     * 路径切换（没有则创建）
     *
     * @param ftpClient FTP服务器
     * @param path      路径
     */
    public boolean changeAndMakeWorkingDir(FTPClient ftpClient, String path) {
        boolean flag = false;
        try {
            String[] path_array = path.split("/");
            for (String s : path_array) {
                boolean b = ftpClient.changeWorkingDirectory(s);
                if (!b) {
                    ftpClient.makeDirectory(s);
                    ftpClient.changeWorkingDirectory(s);
                }
            }
            flag = true;
        } catch (IOException e) {
            log.error("路径切换异常", e);
        }
        return flag;
    }

    /**
     * 从FTP下载到本地文件夹
     *
     * @param ftpClient      FTP服务器
     * @param pathName       路径
     * @param targetFileName 文件名
     * @param localPath      本地路径
     * @return
     */
    public boolean downloadFile(FTPClient ftpClient, String pathName, String targetFileName, String localPath) {
        boolean flag = false;
        OutputStream os = null;
        try {
            System.out.println("开始下载文件");
            //切换FTP目录
            ftpClient.changeWorkingDirectory(pathName);
            ftpClient.enterLocalPassiveMode();
            FTPFile[] ftpFiles = ftpClient.listFiles();
            for (FTPFile file : ftpFiles) {
                String ftpFileName = file.getName();
                if (targetFileName.equalsIgnoreCase(ftpFileName)) {
                    File localFile = new File(localPath + targetFileName);
                    os = new FileOutputStream(localFile);
                    ftpClient.retrieveFile(file.getName(), os);
                    os.close();
                }
            }
            ftpClient.logout();
            flag = true;
            log.info("下载文件成功");
        } catch (Exception e) {
            log.error("下载文件失败", e);
        } finally {
            closeFtpClient(ftpClient);
            closeStream(os);
        }
        return flag;
    }


    public static void main(String[] args) {
        String hostname = "112.124.53.14";
        int port = 21;
        String username = "My";
        String password = "My.123456";
        String ftpPath = "/ftpfiles";

        FtpClientUtil ftpClientUtil = FtpClientUtil.getInstance(hostname, port, username, password);

        Integer code = new Random().nextInt(9999);
        String fileName = "GSNGGIS_" + DateUtils.dateTimeNow() + (code < 1000 ? code + 1000 : code) + ".xml";

        List<AaaaLog> logList = new ArrayList<>();
        AaaaLog aaaaLog = new AaaaLog();
        aaaaLog.setAppLogId(UUID.randomUUID().toString().replace("-", ""));
        aaaaLog.setSessionId(UUID.randomUUID().toString().replace("-", ""));
        aaaaLog.setOperateTime(DateUtils.getTime());
        aaaaLog.setOpLevelId("1");
        aaaaLog.setClientAddress("192.168.124.33");
        aaaaLog.setClientNetworkAddress("192.168.124.33");
        aaaaLog.setOperateResult("0");
        aaaaLog.setSubAccountName("zhangsan");
        aaaaLog.setModuleId(AaaaEnum.LOGON.getType());
        aaaaLog.setModuleName(AaaaEnum.LOGON.getName());
        aaaaLog.setOpTypeId(AaaaEnum.OPONE.getType());
        aaaaLog.setOpTypeName(AaaaEnum.OPONE.getName());
        aaaaLog.setOperateContent("zhangsan" + "进行了" + aaaaLog.getOpTypeName());
        logList.add(aaaaLog);

        AaaaLogRspInfo aaaaLogRspInfo = new AaaaLogRspInfo();
        aaaaLogRspInfo.setAaaaLogList(logList);
        String parse2Xml = XmlParserUtil.parse2Xml(aaaaLogRspInfo, AaaaLogRspInfo.class);
        log.info("xml报文内容：{}", parse2Xml);

//        File file = new File("d://test.xml");
//        InputStream inputStream = new FileInputStream(file);
        InputStream inputStream = new ByteArrayInputStream(parse2Xml.getBytes());
        ftpClientUtil.uploadFileToFtp(ftpPath, fileName, inputStream);
    }

}
